package com.cdks.wuxiu.api.service.redis;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.cdks.wuxiu.api.component.constant.Constant;
import com.cdks.wuxiu.api.model.dto.CloudStorageDTO;
import com.cdks.wuxiu.api.model.dto.KmsgDataDTO;
import com.cdks.wuxiu.api.util.TimeUtils;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;


/**
 * Redis 业务类
 */
@Slf4j
@Component
public class RedisServiceImpl implements RedisService {
    @Resource(name = "redisTemplate00")
    private RedisTemplate<String, String> redisTemplate00;       
    @Resource(name = "redisTemplate01")
    private RedisTemplate<String, String> redisTemplate01;
    @Resource(name = "redisTemplate02")
    private RedisTemplate<String, String> redisTemplate02;
    @Resource(name = "redisTemplate03")
    private RedisTemplate<String, String> redisTemplate03;
    @Resource(name = "redisTemplate05")
    private RedisTemplate<String, String> redisTemplate05;
    @Resource(name = "redisTemplate06")
    private RedisTemplate<String, String> redisTemplate06;
    @Resource(name = "redisTemplate07")
    private RedisTemplate<String, String> redisTemplate07;


    @Override
    public int setSmsCode(String phone, String code) {
        String key  = phone + ":smscode";
        redisTemplate00.opsForValue().set(key, code, Constant.TIME_VALUE_10_MINUTES, TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public String getSmsCode(String phone) {
        String key  = phone + ":smscode";
        return redisTemplate00.opsForValue().get(key);
    }

    @Override
    public int addSmsCount(String phone) {
        String key  = phone + ":smscnt";

        Long ret  = redisTemplate00.opsForValue().increment(key);
        redisTemplate00.expire(key, Constant.TIME_VALUE_24_HOURS, TimeUnit.SECONDS);

        return ret.intValue();
    }

    @Override
    public int decSmsCount(String phone) {
        String key  = phone + ":smscnt";
        redisTemplate00.opsForValue().decrement(key);

        return 0;
    }

    @Override
    public boolean setUserToken(long userId, String encToken, boolean force) {
        String key  = userId + ":token";

        if (force)
        {
            redisTemplate01.opsForValue().set(key, encToken, Constant.TIME_VALUE_10_MINUTES, TimeUnit.SECONDS);

            return true;
        }

        return redisTemplate01.opsForValue().setIfAbsent(key, encToken, Constant.TIME_VALUE_10_MINUTES, TimeUnit.SECONDS);
    }

    @Override
    public String getUserToken(long userId) {
        String key  = userId + ":token";
        return redisTemplate01.opsForValue().get(key);
    }

    @Override
    public boolean setChalln(long userId, String challn) {
        String key  = userId + ":challn";

        return redisTemplate01.opsForValue().setIfAbsent(key, challn, Constant.TIME_VALUE_30_SECONDS, TimeUnit.SECONDS);
    }

    @Override
    public String getChalln(long userId) {
        String key  = userId + ":challn";
        return redisTemplate01.opsForValue().get(key);
    }

    @Override
    public int delUserToken(long userId) {
        redisTemplate01.delete(userId + ":token");

        return 0;
    }

    @Override
    public int setKmsgAuthData(long userId, KmsgDataDTO dto) {
        String key  = userId + ":kmsgAuthData";

        redisTemplate02.opsForValue().set(key, JSONUtil.toJsonStr(dto));
        redisTemplate02.expire(key, dto.getExpire() - 60, TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public String getKmsgAuthData(long userId) {
        String key  = userId + ":kmsgAuthData";
        return redisTemplate02.opsForValue().get(key);
    }

    @Override
    public int setCallToken(long userId, String ucid, String callToken) {
        String key  = "callToken:" + userId + ":" + ucid;

        redisTemplate03.opsForValue().set(key, callToken);
        redisTemplate03.expire(key, Constant.TIME_VALUE_03_HOURS - 60, TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public String getCallToken(long userId, String ucid) {
        String key  = "callToken:" + userId + ":" + ucid;
        return redisTemplate03.opsForValue().get(key);
    }

    @Override
    public String getOssAuthData() {
        String key  = "ossAccessData";
        return (String) redisTemplate05.opsForValue().get(key);
    }

    @Override
    public int setOssAuthData(CloudStorageDTO ossData) {
        String key  = "ossAccessData";
        long ttl    = ossData.getExpiration() - TimeUtils.getTimeSecond() - 60;
        redisTemplate05.opsForValue().set(key, JSONUtil.toJsonStr(ossData));
        redisTemplate05.expire(key, Math.max(ttl, 1), TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public int setCallKeepTime(long userId, long time, String ucid) {
        String key  = "callKeep:" + ucid;

        redisTemplate03.opsForHash().put(key, String.valueOf(userId), String.valueOf(time));
        redisTemplate03.expire(key, Constant.TIME_VALUE_07_DAYS, TimeUnit.SECONDS);

        return 0;
    } 

    @Override
    public int getCallKeepTime(long userId, String ucid) {
        String key  = "callKeep:" + ucid;
        Object ret  = redisTemplate03.opsForHash().get(key, String.valueOf(userId));
        if (ret == null)
        {
            return 0;
        }

        return Integer.valueOf((String) ret);
    }

    @Override
    public String getLastMessageMd5(long userId) {
        String key  = userId + ":lastMsgMd5";
        return redisTemplate02.opsForValue().get(key);
    }

    @Override
    public int setLastMessageMd5(long userId, String md5) {
        String key  = userId + ":lastMsgMd5";

        redisTemplate02.opsForValue().set(key, md5);
        redisTemplate02.expire(key, Constant.TIME_VALUE_60_SECONDS, TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public int saveRepeatMessage(long userId, String md5, String msg) {
        String key  = userId + ":repeatMsg";
        //重复消息内容
        redisTemplate02.opsForHash().put(key, md5, msg);

        return 0;
    }

    @Override
    public int getMessageRate(long senderId, long recverId) {
        String key   = senderId + ":" + recverId + ":msgRate";
        String rate  = redisTemplate02.opsForValue().get(key);
        if (rate == null)
        {
            return 0;
        }
        else
        {
            return Integer.parseInt(rate);
        }
    }

    @Override
    public int delMessageRate(long senderId, long recverId) {
        String key   = senderId + ":" + recverId + ":msgRate";
        Boolean ret  = redisTemplate02.delete(key);

        return ret ? 0 : -1;
    }

    @Override
    public int decMessageRate(long senderId, long recverId) {
        String key   = senderId + ":" + recverId + ":msgRate";
        String rate  = redisTemplate02.opsForValue().get(key);
        if (rate != null)
        {
            return redisTemplate02.opsForValue().decrement(key).intValue();
        }

        return 0;
    }

    @Override
    public int ttlMessageRate(long senderId, long recverId) {
        String key   = senderId + ":" + recverId + ":msgRate";
        long ret  = redisTemplate02.getExpire(key, TimeUnit.SECONDS);

        return (int)ret;
    }

    @Override
    public int addMessageRate(long senderId, long recverId) {
        String key   = senderId + ":" + recverId + ":msgRate";
        int rate     = redisTemplate02.opsForValue().increment(key).intValue();
        if (rate == 1)
        {
            redisTemplate02.expire(key, Constant.TIME_VALUE_24_HOURS, TimeUnit.SECONDS);
        }

        return rate;
    }

    @Override
    public int addMessageCount(long senderId, long recverId) {
        String key   = senderId + ":" + recverId + ":msgCount";
        int rate     = redisTemplate02.opsForValue().increment(key).intValue();
        if (rate == 1)
        {
            redisTemplate02.expire(key, Constant.TIME_VALUE_24_HOURS, TimeUnit.SECONDS);
        }

        return rate;
    }

    @Override
    public int ttlChatBanTime(long senderId) {
        String key   = senderId + ":banTime";
        long ret  = redisTemplate02.getExpire(key, TimeUnit.SECONDS);

        return (int)ret;
    }

    @Override
    public int addChatBanCount(long senderId) {
        int times[]  = {30, 60, 2*60, 5*60, 10*60, 20*60, 30*60, 60*60, 2*60*60, 4*60*60, 8*60*60};
        String key   = senderId + ":banCount";
        int ret  = redisTemplate02.opsForValue().increment(key).intValue();
        if (ret == 1)
        {
            redisTemplate02.expire(key, Constant.TIME_VALUE_24_HOURS, TimeUnit.SECONDS);

            return Constant.TIME_VALUE_24_HOURS;
        }
        else
        {
            int ttl  = times[ret - 2];
            redisTemplate02.opsForValue().set(senderId + ":banTime", String.valueOf(ttl), ttl, TimeUnit.SECONDS);

            return ttl;
        }
    }

    @Override
    public int saveNoticedCallee(long userId, long matchUserId) {
        String key   = "call:notice:" + userId;

        redisTemplate03.opsForZSet().add(key, String.valueOf(matchUserId), TimeUtils.getTimeSecond());
        redisTemplate03.expire(key, Constant.TIME_VALUE_30_MINUTES, TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public Set<String> getNoticedCallee(long userId) {
        String key  = "call:notice:" + userId;
        long now    = TimeUtils.getTimeSecond();

        return redisTemplate03.opsForZSet().rangeByScore(key, now - Constant.TIME_VALUE_30_MINUTES, now);
    }

    @Override
    public int saveRandCall(long caller, long callee) {
        String key   = "call:randCall:" + caller;

        redisTemplate03.opsForSet().add(key, String.valueOf(callee));
        redisTemplate03.expire(key, Constant.TIME_VALUE_30_SECONDS, TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public int removeRandCall(long caller, long callee) {
        String key   = "call:randCall:" + caller;
        long ret  = redisTemplate03.opsForSet().remove(key, String.valueOf(callee));

        return (int)ret;
    }

    @Override
    public int deleteRandCall(long caller) {
        String key   = "call:randCall:" + caller;
        redisTemplate03.delete(key);

        return 0;
    }

    @Override
    public Set<String> getRandCall(long caller) {
        String key   = "call:randCall:" + caller;
        return redisTemplate03.opsForSet().members(key);
    }

    @Override
    public int setRecordStart(String ucid) {
        String key  = "record:" + ucid;

        Boolean ret  = redisTemplate03.opsForHash().putIfAbsent(key, "status", String.valueOf(Constant.RECORD_STATUS_START));
        if (ret)
        {
            redisTemplate03.expire(key, Constant.TIME_VALUE_03_HOURS, TimeUnit.SECONDS);

            return 0;
        }
        
        return -1;
    }

    @Override
    public int saveRecordInfo(String ucid, Map<String, Object> info) {
        String key  = "record:" + ucid;
        redisTemplate03.opsForHash().putAll(key, info);

        return 0;
    }

    @Override
    public Map<Object, Object> getRecordInfo(String ucid) {
        String key  = "record:" + ucid;
        return redisTemplate03.opsForHash().entries(key);
    }

    @Override
    public String getInviterInfo(String ip) {
        String info  = redisTemplate06.opsForValue().get(ip);
        if (info == null)
        {
            return null;
        }

        JSONObject json  = JSONUtil.parseObj(info);

        return json.getStr("inviter");
    }

    @Override
    public int saveWaitCall(long callee, String ucid) {
        String key  = "call:waitCall:" + callee;

        redisTemplate03.opsForZSet().add(key, ucid, TimeUtils.getTimeSecond());
        redisTemplate03.expire(key, Constant.TIME_VALUE_60_SECONDS, TimeUnit.SECONDS);

        return 0;
    }

    @Override
    public String getWaitCall(long callee) {
        String key  = "call:waitCall:" + callee;
        Set<String>  ucid = redisTemplate03.opsForZSet().range(key, 0, 0);

        if (!ucid.isEmpty())
        {
            return ucid.iterator().next();
        }
        else
        {
            return null;
        }
    }

    @Override
    public int removeWaitCall(long callee, String ucid) {
        String key  = "call:waitCall:" + callee;
        log.info("removeWaitCall: " + key + ", " + ucid);
        redisTemplate03.opsForZSet().remove(key, ucid);

        return 0;
    }
}
